package com.greateamd.timetableasy.server.dao.util;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.greateamd.timetableasy.domain.PersistableEntity;
import com.greateamd.timetableasy.server.dao.IBaseDao;

public class AbstractHibernateDAO<T extends PersistableEntity, ID extends Serializable> extends HibernateDaoSupport implements IBaseDao<T, ID> {
	
	protected Logger logger = Logger.getLogger(this.getClass());

	private T type;
	public AbstractHibernateDAO(T type) {
		this.type = type;
	}
	
	@Override
	public void delete(final T obj) throws HibernateException,SQLException, IllegalAccessException{
		logger.debug("Delete "+type.getClass().getSimpleName()+" with id " + obj.getId());
		getHibernateTemplate().execute(new HibernateCallback<Void>() {
	         public Void doInHibernate(Session session) throws HibernateException,SQLException {
	             session.delete(obj);
	             return null;
	         }
	     });
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> getAll() throws HibernateException,SQLException{
		return (List) getHibernateTemplate().execute(new HibernateCallback<List>() {
			public List doInHibernate(Session session) throws HibernateException,SQLException {
				String requeteFrom = type.getClass().getName();
        		List result = session.createQuery("from "+requeteFrom).list();
                return result;
            }
        });        
	}

	@SuppressWarnings("unchecked")
	@Override
	public T getById(final ID id) throws HibernateException,SQLException{
        return getHibernateTemplate().execute(new HibernateCallback<T>() {
			public T doInHibernate(Session session) throws HibernateException,SQLException {
				return (T) session.get(type.getClass(), id);
            }
        });        
	}

	@Override
	public void save(final T obj) throws HibernateException,SQLException {
        getHibernateTemplate().execute(new HibernateCallback<Void>() {
	         public Void doInHibernate(Session session) throws HibernateException,SQLException {
	             session.save(obj);
	             return null;
	         }
	     });
	}

	@Override
	public void save(final List<T> obj) throws HibernateException,SQLException{
        getHibernateTemplate().execute(new HibernateCallback<Void>() {
	         public Void doInHibernate(Session session) throws HibernateException,SQLException {
	        	 for(T toSave : obj){
	        		 session.save(toSave);
	        	 }
	             return null;
	         }
	     });
	}
	
	@Override
	public void update(final T obj) throws HibernateException,SQLException, IllegalAccessException{
        getHibernateTemplate().execute(new HibernateCallback<Void>() {
	         public Void doInHibernate(Session session) throws HibernateException,SQLException {
	             session.update(obj);
	             return null;
	         }
	     });
	}
	
	@Override
	public void saveOrUpdate(final T obj) throws HibernateException,SQLException{
        getHibernateTemplate().execute(new HibernateCallback<Void>() {
	         public Void doInHibernate(Session session) throws HibernateException,SQLException {
	             session.saveOrUpdate(obj);
	             return null;
	         }
	     });
	}
	
	@Override
	public Integer getRowCount() throws HibernateException,SQLException{
        return getHibernateTemplate().execute(new HibernateCallback<Integer>() {
	         public Integer doInHibernate(Session session) throws HibernateException,SQLException {
	            Criteria criteria = session.createCriteria(type.getClass());
	     		criteria.setProjection(Projections.rowCount());
	    		return (Integer) criteria.uniqueResult();
	         }
	     });
	}
}
